<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Text2SQL评估系统</title>
    <script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
    <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
    <link href="https://cdn.jsdelivr.net/npm/element-plus@2.4.4/dist/index.css" rel="stylesheet">
    <script src="https://unpkg.com/element-plus@2.4.4/dist/index.full.js"></script>
    <style>
        body {
            margin: 0;
            padding: 0;
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            min-height: 100vh;
        }
        
        .container {
            max-width: 1200px;
            margin: 0 auto;
            padding: 20px;
        }
        
        .header {
            text-align: center;
            color: white;
            margin-bottom: 30px;
        }
        
        .header h1 {
            font-size: 2.5rem;
            margin-bottom: 10px;
            text-shadow: 2px 2px 4px rgba(0,0,0,0.3);
        }
        
        .header p {
            font-size: 1.2rem;
            opacity: 0.9;
        }
        
        .card {
            background: white;
            border-radius: 15px;
            box-shadow: 0 10px 30px rgba(0,0,0,0.2);
            margin-bottom: 20px;
            overflow: hidden;
        }
        
        .card-header {
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            color: white;
            padding: 20px;
            font-size: 1.3rem;
            font-weight: bold;
        }
        
        .card-body {
            padding: 25px;
        }
        
        .form-section {
            margin-bottom: 30px;
        }
        
        .form-row {
            display: flex;
            gap: 20px;
            margin-bottom: 20px;
        }
        
        .form-group {
            flex: 1;
        }
        
        .form-group label {
            display: block;
            margin-bottom: 8px;
            font-weight: bold;
            color: #333;
        }
        
        .form-group textarea,
        .form-group input {
            width: 100%;
            padding: 12px;
            border: 2px solid #e1e5e9;
            border-radius: 8px;
            font-size: 14px;
            transition: border-color 0.3s;
        }
        
        .form-group textarea:focus,
        .form-group input:focus {
            outline: none;
            border-color: #667eea;
        }
        
        .form-group textarea {
            height: 100px;
            resize: vertical;
        }
        
        .btn {
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            color: white;
            border: none;
            padding: 12px 30px;
            border-radius: 8px;
            font-size: 16px;
            font-weight: bold;
            cursor: pointer;
            transition: transform 0.2s, box-shadow 0.2s;
        }
        
        .btn:hover {
            transform: translateY(-2px);
            box-shadow: 0 5px 15px rgba(0,0,0,0.2);
        }
        
        .btn:disabled {
            opacity: 0.6;
            cursor: not-allowed;
            transform: none;
        }
        
        .btn-secondary {
            background: linear-gradient(135deg, #6c757d 0%, #495057 100%);
        }
        
        .btn-success {
            background: linear-gradient(135deg, #28a745 0%, #20c997 100%);
        }
        
        .btn-danger {
            background: linear-gradient(135deg, #dc3545 0%, #fd7e14 100%);
        }
        
        .result-section {
            margin-top: 30px;
        }
        
        .result-card {
            background: #f8f9fa;
            border-radius: 10px;
            padding: 20px;
            margin-bottom: 15px;
            border-left: 4px solid #667eea;
        }
        
        .result-title {
            font-weight: bold;
            color: #333;
            margin-bottom: 10px;
            font-size: 1.1rem;
        }
        
        .result-content {
            color: #666;
            line-height: 1.6;
        }
        
        .score-display {
            display: inline-block;
            background: #667eea;
            color: white;
            padding: 5px 15px;
            border-radius: 20px;
            font-weight: bold;
            margin: 5px;
        }
        
        .score-high {
            background: #28a745;
        }
        
        .score-medium {
            background: #ffc107;
            color: #333;
        }
        
        .score-low {
            background: #dc3545;
        }
        
        .loading {
            text-align: center;
            padding: 40px;
            color: #666;
        }
        
        .error {
            background: #f8d7da;
            color: #721c24;
            padding: 15px;
            border-radius: 8px;
            margin: 10px 0;
            border: 1px solid #f5c6cb;
        }
        
        .success {
            background: #d4edda;
            color: #155724;
            padding: 15px;
            border-radius: 8px;
            margin: 10px 0;
            border: 1px solid #c3e6cb;
        }
        
        .test-data-item {
            background: white;
            border: 1px solid #e1e5e9;
            border-radius: 8px;
            padding: 15px;
            margin-bottom: 10px;
            cursor: pointer;
            transition: all 0.3s;
        }
        
        .test-data-item:hover {
            border-color: #667eea;
            box-shadow: 0 2px 8px rgba(0,0,0,0.1);
        }
        
        .test-data-item.selected {
            border-color: #667eea;
            background: #f0f4ff;
        }
        
        .test-data-question {
            font-weight: bold;
            color: #333;
            margin-bottom: 8px;
        }
        
        .test-data-sql {
            color: #666;
            font-family: 'Courier New', monospace;
            font-size: 14px;
            background: #f8f9fa;
            padding: 8px;
            border-radius: 4px;
        }
        
        .stats-grid {
            display: grid;
            grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
            gap: 20px;
            margin: 20px 0;
        }
        
        .stat-card {
            background: white;
            padding: 20px;
            border-radius: 10px;
            text-align: center;
            box-shadow: 0 2px 10px rgba(0,0,0,0.1);
        }
        
        .stat-value {
            font-size: 2rem;
            font-weight: bold;
            color: #667eea;
            margin-bottom: 5px;
        }
        
        .stat-label {
            color: #666;
            font-size: 0.9rem;
        }
    </style>
</head>
<body>
    <div id="app">
        <div class="container">
            <div class="header">
                <h1>Text2SQL评估系统</h1>
                <p>基于LLM的SQL生成准确率评估工具</p>
            </div>
            
            <!-- 单个SQL评估 -->
            <div class="card">
                <div class="card-header">
                    <i class="el-icon-edit"></i> 单个SQL评估
                </div>
                <div class="card-body">
                    <div class="form-section">
                        <div class="form-group">
                            <label>问题描述</label>
                            <textarea v-model="singleEvaluation.question" placeholder="请输入自然语言问题..."></textarea>
                        </div>
                        
                        <div class="form-row">
                            <div class="form-group">
                                <label>预测的SQL语句</label>
                                <textarea v-model="singleEvaluation.predictedSql" placeholder="请输入预测的SQL语句..."></textarea>
                            </div>
                            <div class="form-group">
                                <label>标准SQL语句</label>
                                <textarea v-model="singleEvaluation.groundTruthSql" placeholder="请输入标准SQL语句..."></textarea>
                            </div>
                        </div>
                        
                        <button class="btn" @click="evaluateSingle" :disabled="isLoading">
                            {{ isLoading ? '评估中...' : '开始评估' }}
                        </button>
                    </div>
                    
                    <div v-if="singleResult" class="result-section">
                        <div class="result-card">
                            <div class="result-title">SQL准确率评估结果</div>
                            <div class="result-content">
                                <p><strong>完全匹配:</strong> 
                                    <span :class="singleResult.sql_accuracy.exact_match ? 'score-display score-high' : 'score-display score-low'">
                                        {{ singleResult.sql_accuracy.exact_match ? '是' : '否' }}
                                    </span>
                                </p>
                                <p><strong>语义相似度:</strong> 
                                    <span :class="getScoreClass(singleResult.sql_accuracy.semantic_score)" class="score-display">
                                        {{ (singleResult.sql_accuracy.semantic_score * 100).toFixed(1) }}%
                                    </span>
                                </p>
                                <p><strong>标准化预测SQL:</strong> <code>{{ singleResult.sql_accuracy.normalized_predicted }}</code></p>
                                <p><strong>标准化标准SQL:</strong> <code>{{ singleResult.sql_accuracy.normalized_ground_truth }}</code></p>
                            </div>
                        </div>
                        
                        <div v-if="singleResult.ragas_evaluation" class="result-card">
                            <div class="result-title">RAGAS评估结果</div>
                            <div class="result-content">
                                <p><strong>忠实度:</strong> 
                                    <span :class="getScoreClass(singleResult.ragas_evaluation.faithfulness.mean)" class="score-display">
                                        {{ (singleResult.ragas_evaluation.faithfulness.mean * 100).toFixed(1) }}%
                                    </span>
                                </p>
                                <p><strong>答案相关性 (开源模型):</strong> 
                                    <span :class="getScoreClass(singleResult.ragas_evaluation.answer_relevancy_opensource.mean)" class="score-display">
                                        {{ (singleResult.ragas_evaluation.answer_relevancy_opensource.mean * 100).toFixed(1) }}%
                                    </span>
                                </p>
                                <p><strong>答案相关性 (OpenAI模型):</strong> 
                                    <span :class="getScoreClass(singleResult.ragas_evaluation.answer_relevancy_openai.mean)" class="score-display">
                                        {{ (singleResult.ragas_evaluation.answer_relevancy_openai.mean * 100).toFixed(1) }}%
                                    </span>
                                </p>
                            </div>
                        </div>
                    </div>
                </div>
            </div>


            
            <!-- 错误和成功消息 -->
            <div v-if="errorMessage" class="error">
                {{ errorMessage }}
            </div>
            
            <div v-if="successMessage" class="success">
                {{ successMessage }}
            </div>
        </div>
    </div>

    <script>
        const { createApp } = Vue;
        
        createApp({
            data() {
                return {
                    // 单个评估
                    singleEvaluation: {
                        question: '',
                        predictedSql: '',
                        groundTruthSql: ''
                    },
                    singleResult: null,
                    
                    // 批量评估
                    testData: [],
                    selectedItems: [],
                    batchResult: null,
                    
                    // 状态
                    isLoading: false,
                    errorMessage: '',
                    successMessage: '',
                    
                    // API配置
                    apiBaseUrl: 'http://localhost:5000/api'
                }
            },
            methods: {
                // 单个SQL评估
                async evaluateSingle() {
                    if (!this.singleEvaluation.predictedSql || !this.singleEvaluation.groundTruthSql) {
                        this.showError('请填写预测SQL和标准SQL');
                        return;
                    }
                    
                    this.isLoading = true;
                    this.clearMessages();
                    
                    try {
                        const response = await axios.post(`${this.apiBaseUrl}/evaluate-sql`, {
                            question: this.singleEvaluation.question,
                            predicted_sql: this.singleEvaluation.predictedSql,
                            ground_truth_sql: this.singleEvaluation.groundTruthSql
                        });
                        
                        if (response.data.success) {
                            this.singleResult = response.data;
                            this.showSuccess('单个SQL评估完成');
                        } else {
                            this.showError(response.data.error || '评估失败');
                        }
                    } catch (error) {
                        this.showError('评估请求失败: ' + error.message);
                    } finally {
                        this.isLoading = false;
                    }
                },

                
                // 切换选择项
                toggleSelection(index) {
                    const idx = this.selectedItems.indexOf(index);
                    if (idx > -1) {
                        this.selectedItems.splice(idx, 1);
                    } else {
                        this.selectedItems.push(index);
                    }
                },
                
                // 清空选择
                clearSelection() {
                    this.selectedItems = [];
                },
                
                // 评估选中的项目
                async evaluateSelected() {
                    if (this.selectedItems.length === 0) {
                        this.showError('请选择要评估的项目');
                        return;
                    }
                    
                    this.isLoading = true;
                    this.clearMessages();
                    
                    try {
                        const evaluations = this.selectedItems.map(index => ({
                            question: this.testData[index].question,
                            predicted_sql: this.testData[index].sql, // 这里使用标准SQL作为预测SQL进行演示
                            ground_truth_sql: this.testData[index].sql
                        }));
                        
                        const response = await axios.post(`${this.apiBaseUrl}/evaluate-batch`, {
                            evaluations: evaluations
                        });
                        
                        if (response.data.success) {
                            this.batchResult = response.data;
                            this.showSuccess(`批量评估完成，共评估 ${response.data.summary.total_evaluations} 项`);
                        } else {
                            this.showError(response.data.error || '批量评估失败');
                        }
                    } catch (error) {
                        this.showError('批量评估失败: ' + error.message);
                    } finally {
                        this.isLoading = false;
                    }
                },
                
                // 获取分数样式类
                getScoreClass(score) {
                    if (score >= 0.8) return 'score-high';
                    if (score >= 0.6) return 'score-medium';
                    return 'score-low';
                },
                
                // 显示错误消息
                showError(message) {
                    this.errorMessage = message;
                    this.successMessage = '';
                    setTimeout(() => {
                        this.errorMessage = '';
                    }, 5000);
                },
                
                // 显示成功消息
                showSuccess(message) {
                    this.successMessage = message;
                    this.errorMessage = '';
                    setTimeout(() => {
                        this.successMessage = '';
                    }, 3000);
                },
                
                // 清空消息
                clearMessages() {
                    this.errorMessage = '';
                    this.successMessage = '';
                }
            },
            mounted() {
                // 页面加载时自动加载测试数据
                this.loadTestData();
            }
        }).mount('#app');
    </script>
</body>
</html>
